package edu.northwestern.cbits.purple_robot_manager.probes.builtin; import java.util.ArrayList; import java.util.Map; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.preference.CheckBoxPreference; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; import android.support.v7.media.MediaControlIntent; import android.support.v7.media.MediaRouteSelector; import android.support.v7.media.MediaRouter; import com.google.android.gms.cast.CastMediaControlIntent; import edu.northwestern.cbits.purple_robot_manager.R; import edu.northwestern.cbits.purple_robot_manager.activities.settings.FlexibleListPreference; import edu.northwestern.cbits.purple_robot_manager.logging.LogManager; import edu.northwestern.cbits.purple_robot_manager.probes.Probe; public class MediaRouterDeviceProbe extends Probe { private static final boolean DEFAULT_ENABLED = false; protected static final String ROUTES = "ROUTES"; protected static final String ROUTE_COUNT = "ROUTE_COUNT"; private static final String FREQUENCY = "config_probe_mediarouter_frequency"; private static final String ENABLED = "config_probe_mediarouter_enabled"; private final Handler _handler = new Handler(Looper.getMainLooper()); private long _lastCheck = 0; private final long _lastScan = 0; private boolean _isScanning = false; @Override public String getPreferenceKey() { return "built_in_mediarouter"; } private final MediaRouter.Callback _callback = new MediaRouter.Callback() { @Override public void onProviderAdded(MediaRouter router, MediaRouter.ProviderInfo info) { // Log.e("PR", "PROVIDER ADD: " + info + " -- " + // info.getPackageName()); } @Override public void onProviderChanged(MediaRouter router, MediaRouter.ProviderInfo info) { // Log.e("PR", "PROVIDER CHANGE: " + info + " -- " + // info.getPackageName()); } @Override public void onProviderRemoved(MediaRouter router, MediaRouter.ProviderInfo info) { // Log.e("PR", "PROVIDER REMOVE: " + info + " -- " + // info.getPackageName()); } @Override public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo route) { // Log.e("PR", "ROUTE ADD: " + route.getName() + " -- " + // route.getPlaybackType() + " -- " + route.getVolume() + "/" + // route.getVolumeMax()); } @Override public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) { // Log.e("PR", "ROUTE CHANGE: " + route.getName() + " -- " + // route.getPlaybackType() + " -- " + route.getVolume() + "/" + // route.getVolumeMax()); } @Override public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo route) { // Log.e("PR", "ROUTE REMOVE: " + route.getName() + " -- " + // route.getPlaybackType() + " -- " + route.getVolume() + "/" + // route.getVolumeMax()); } }; @Override public String name(Context context) { return "edu.northwestern.cbits.purple_robot_manager.probes.builtin.MediaRouterDeviceProbe"; } @Override public String title(Context context) { return context.getString(R.string.title_mediarouter_probe); } @Override public String probeCategory(Context context) { return context.getResources().getString(R.string.probe_other_devices_category); } @Override public boolean isEnabled(final Context context) { if (super.isEnabled(context)) { SharedPreferences prefs = Probe.getPreferences(context); if (prefs.getBoolean(MediaRouterDeviceProbe.ENABLED, MediaRouterDeviceProbe.DEFAULT_ENABLED)) { final long now = System.currentTimeMillis(); synchronized (this) { long freq = Long.parseLong(prefs.getString(MediaRouterDeviceProbe.FREQUENCY, Probe.DEFAULT_FREQUENCY)); final MediaRouterDeviceProbe me = this; if (now - this._lastCheck > freq) { this._lastCheck = now; this._handler.post(new Runnable() { @Override public void run() { MediaRouter router = MediaRouter.getInstance(context); Bundle bundle = new Bundle(); bundle.putString("PROBE", me.name(context)); bundle.putLong("TIMESTAMP", System.currentTimeMillis() / 1000); if (now - me._lastScan > 30000 && me._isScanning) { router.removeCallback(me._callback); me._isScanning = false; } else if (now - me._lastScan > 300000 && me._isScanning == false) { MediaRouteSelector.Builder builder = new MediaRouteSelector.Builder(); builder = builder.addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO); builder = builder.addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO); builder = builder.addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK); builder = builder.addControlCategory(CastMediaControlIntent.CATEGORY_CAST); router.addCallback(builder.build(), me._callback, MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN); } ArrayList<Bundle> routes = new ArrayList<>(); for (MediaRouter.ProviderInfo info : router.getProviders()) { for (MediaRouter.RouteInfo route : info.getRoutes()) { Bundle routeBundle = new Bundle(); routeBundle.putString("PACKAGE", info.getPackageName()); routeBundle.putString("NAME", route.getName()); routeBundle.putString("DESCRIPTION", route.getDescription()); routeBundle.putBoolean("ENABLED", route.isEnabled()); routeBundle.putBoolean("DEFAULT", route.isDefault()); routeBundle.putBoolean("SELECTED", route.isSelected()); routeBundle.putInt("VOLUME", route.getVolume()); routeBundle.putInt("VOLUME_MAX", route.getVolumeMax()); switch (route.getPlaybackType()) { case MediaRouter.RouteInfo.PLAYBACK_TYPE_LOCAL: routeBundle.putString("TYPE", "local"); break; case MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE: routeBundle.putString("TYPE", "remote"); break; } // routeBundle.putBundle("EXTRAS", // route.getExtras()); routes.add(routeBundle); } } bundle.putParcelableArrayList(MediaRouterDeviceProbe.ROUTES, routes); bundle.putInt(MediaRouterDeviceProbe.ROUTE_COUNT, routes.size()); bundle.putString("SELECTED_ROUTE", router.getSelectedRoute().getName()); bundle.putString("DEFAULT_ROUTE", router.getDefaultRoute().getName()); me.transmitData(context, bundle); } }); } } return true; } } return false; } @Override public void enable(Context context) { SharedPreferences prefs = Probe.getPreferences(context); Editor e = prefs.edit(); e.putBoolean(MediaRouterDeviceProbe.ENABLED, true); e.commit(); } @Override public void disable(Context context) { SharedPreferences prefs = Probe.getPreferences(context); Editor e = prefs.edit(); e.putBoolean(MediaRouterDeviceProbe.ENABLED, false); e.commit(); } @Override public String summarizeValue(Context context, Bundle bundle) { String name = bundle.getString("SELECTED_ROUTE"); double volume = -1; double volumeMax = -1; ArrayList<Bundle> bundles = bundle.getParcelableArrayList("ROUTES"); for (Bundle route : bundles) { if (name.equals(route.get("NAME"))) { volume = route.getDouble("VOLUME"); volumeMax = route.getDouble("VOLUME_MAX"); } } return context.getString(R.string.summary_mediarouter_probe, name, volume, volumeMax); } @Override public Map<String, Object> configuration(Context context) { Map<String, Object> map = super.configuration(context); SharedPreferences prefs = Probe.getPreferences(context); long freq = Long.parseLong(prefs.getString(MediaRouterDeviceProbe.FREQUENCY, Probe.DEFAULT_FREQUENCY)); map.put(Probe.PROBE_FREQUENCY, freq); return map; } @Override public void updateFromMap(Context context, Map<String, Object> params) { super.updateFromMap(context, params); if (params.containsKey(Probe.PROBE_FREQUENCY)) { Object frequency = params.get(Probe.PROBE_FREQUENCY); if (frequency instanceof Double) { frequency = ((Double) frequency).longValue(); } if (frequency instanceof Long) { SharedPreferences prefs = Probe.getPreferences(context); Editor e = prefs.edit(); e.putString(MediaRouterDeviceProbe.FREQUENCY, frequency.toString()); e.commit(); } } } @Override @SuppressWarnings("deprecation") public PreferenceScreen preferenceScreen(Context context, PreferenceManager manager) { PreferenceScreen screen = super.preferenceScreen(context, manager); screen.setTitle(this.title(context)); screen.setSummary(R.string.summary_mediarouter_probe_desc); CheckBoxPreference enabled = new CheckBoxPreference(context); enabled.setTitle(R.string.title_enable_probe); enabled.setKey(MediaRouterDeviceProbe.ENABLED); enabled.setDefaultValue(MediaRouterDeviceProbe.DEFAULT_ENABLED); screen.addPreference(enabled); FlexibleListPreference duration = new FlexibleListPreference(context); duration.setKey(MediaRouterDeviceProbe.FREQUENCY); duration.setEntryValues(R.array.probe_satellite_frequency_values); duration.setEntries(R.array.probe_satellite_frequency_labels); duration.setTitle(R.string.probe_frequency_label); duration.setDefaultValue(Probe.DEFAULT_FREQUENCY); screen.addPreference(duration); return screen; } @Override public String summary(Context context) { return context.getString(R.string.summary_mediarouter_probe_desc); } @Override public JSONObject fetchSettings(Context context) { JSONObject settings = super.fetchSettings(context); try { JSONObject frequency = new JSONObject(); frequency.put(Probe.PROBE_TYPE, Probe.PROBE_TYPE_LONG); JSONArray values = new JSONArray(); String[] options = context.getResources().getStringArray(R.array.probe_satellite_frequency_values); for (String option : options) { values.put(Long.parseLong(option)); } frequency.put(Probe.PROBE_VALUES, values); settings.put(Probe.PROBE_FREQUENCY, frequency); } catch (JSONException e) { LogManager.getInstance(context).logException(e); } return settings; } }